home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
GNUUCP_2
/
SOURCE
/
SYSDEP.VMS
< prev
next >
Wrap
Text File
|
1989-07-31
|
14KB
|
723 lines
/*
* @(#)sysdep.vms 1.4 87/09/29 Copyright 1987 Free Software Foundation, Inc.
*
* Copying and use of this program are controlled by the terms of the
* GNU Emacs General Public License.
*/
#ifndef lint
char sysdep_version[] = "@(#)sysdep.vms gnuucp Version hoptoad-1.4";
#endif
/*
* Split out of uuslave.c by John Gilmore, 8 August 1987.
* re-worked for VMS by Lol Grant 15th. Aug. 1987, Sept. 87
*/
#include "uucp.h"
#include "sysdep.h"
#include "includes.h"
#define CONTROL "user2:[uucp.uuslave]gnuucp.ctl"
/*
* Exported variables
*/
char sysdep_control[] = CONTROL;
/* Our variables */
struct tt_mode {
char class, type;
short width;
int basic:24;
char length;
long extended;
};
struct iosb_struct {
short status, size, terminator, termsize;
};
static struct tt_mode ttold, ttraw;
static struct iosb_struct ttiosb;
int fdtty; /* File descriptor for tty line */
void sigint(); /* Forward declaration */
/*
* Translation between integer baud rates and VMS baud rates (grumble)
*/
static struct baudtab {
int baudrate, damn_B_code;
} baudtab[] = {
110, TT$C_BAUD_110,
150, TT$C_BAUD_150,
300, TT$C_BAUD_300,
600, TT$C_BAUD_600,
1200, TT$C_BAUD_1200,
1800, TT$C_BAUD_1800,
2400, TT$C_BAUD_2400,
4800, TT$C_BAUD_4800,
9600, TT$C_BAUD_9600,
19200, TT$C_BAUD_19200
};
static int
damn_B(baud)
{
register struct baudtab *b;
for (b = baudtab; b->baudrate < baud; b++)
continue;
if (b->baudrate == baud)
return b->damn_B_code;
return 0;
}
/*
* Open the serial line for an incoming call.
* Argument of NULL or empty string means stdin.
*/
int
openline(ttynam, baud)
char *ttynam;
int baud;
{
int ontheline;
int ret, speed;
struct dsc$descriptor_s tmp;
ontheline = !(ttynam && ttynam[0]); /* FIXME, this is garbage */
speed = 0;
if (ontheline)
ttynam = "SYS$OUTPUT";
tmp.dsc$w_length = strlen(ttynam);
tmp.dsc$a_pointer = ttynam;
tmp.dsc$b_class = DSC$K_CLASS_S;
tmp.dsc$b_dtype = DSC$K_DTYPE_T;
if (((ret = sys$alloc(&tmp, 0, 0, 0)) & 1) != 1) {
exit(0);
}
if (((ret = sys$assign(&tmp, &fdtty, 0, 0)) & 1) != 1) {
DEBUG(0, "Openline: assign %d", ret);
exit(0);
}
ret = sys$qiow(0, fdtty, IO$_SENSEMODE, 0, 0, 0, &ttold,
sizeof(ttold), 0, 0, 0, 0);
bcopy(&ttold,&ttraw,sizeof(struct tt_mode));
ttraw.basic |= TT$M_PASSALL;
ttraw.basic |= TT$M_NOECHO | TT$M_EIGHTBIT;
ttraw.basic &= ~TT$M_WRAP & ~TT$M_HOSTSYNC & ~TT$M_TTSYNC;
if (!ontheline)
speed = damn_B(baud);
ret = sys$qiow(0, fdtty, IO$_SETMODE, 0, 0, 0, &ttraw, sizeof(ttraw),
speed, 0, 0, 0);
return SUCCESS;
/* signal(SIGINT,sigint); */
}
/*
* Open the serial line for an outgoing call.
*/
int
openout(ttynam, baud)
char *ttynam;
int baud;
{
int ret, speed;
struct dsc$descriptor_s tmp;
tmp.dsc$w_length = strlen(ttynam);
tmp.dsc$a_pointer = ttynam;
tmp.dsc$b_class = DSC$K_CLASS_S;
tmp.dsc$b_dtype = DSC$K_DTYPE_T;
if (((ret = sys$alloc(&tmp, 0, 0, 0)) & 1) != 1) {
return -1;
}
if (((ret = sys$assign(&tmp, &fdtty, 0, 0)) & 1) != 1) {
DEBUG(0, "openout: assign %d", ret);
return -1;
}
ret = sys$qiow(0, fdtty, IO$_SENSEMODE, 0, 0, 0, &ttold,
sizeof(ttold), 0, 0, 0, 0);
bcopy(&ttold,&ttraw,sizeof(struct tt_mode));
ttraw.basic |= TT$M_PASSALL;
ttraw.basic |= TT$M_NOECHO | TT$M_EIGHTBIT;
ttraw.basic &= ~TT$M_WRAP & ~TT$M_HOSTSYNC & ~TT$M_TTSYNC;
speed = damn_B(baud);
ret = sys$qiow(0, fdtty, IO$_SETMODE, 0, 0, 0, &ttraw, sizeof(ttraw),
speed, 0, 0, 0);
signal(SIGINT, sigint);
return SUCCESS;
}
/*
* Basement level I/O routines
*
* xwrite() writes a character string to the serial port
* xgetc() returns a character from the serial port, or an EOF for timeout.
* sigint() restores the state of the serial port on exit.
* hangup() hangs up the serial port (e.g. drop DTR).
*/
void
sigint()
{
/* Restore terminal settings on dialout line */
sys$qiow(0, fdtty, IO$_SETMODE, 0, 0, 0, &ttold, sizeof(ttold),
0, 0, 0, 0);
exit(0);
}
/* Nothing is quite as simple in VMS */
xwrite(fd, buf, ctr)
int fd;
char *buf;
int ctr;
{
int ret;
ret = sys$qiow(0, fd, IO$_WRITEVBLK, 0, 0, 0, buf, ctr, 0, 0, 0, 0);
if ((ret & SS$_NORMAL) != 1)
return (0);
return (ctr);
}
/*
* Serial port reading routines
*/
int
xgetc()
{
char c;
long trmmsk[2];
int ret;
trmmsk[0] = 0;
trmmsk[1] = 0;
ret = sys$qiow(0, fdtty, IO$_READVBLK | IO$M_TIMED, &ttiosb, 0, 0,
&c, 1, BYTE_TIMEOUT, trmmsk, 0, 0);
if (ttiosb.status == SS$_TIMEOUT)
return (EOF);
if (ret & SS$_NORMAL)
return (c & 0xff);
return (EOF);
}
/*
* hangup(): hang up the 'fone.
*/
int
hangup()
{
int ret;
xwrite(fdtty, "+++\r", 4); /* This means disconnect to some modems */
/*
This is supposed to hang up the modem. but
causes access violations. It isn't desirable
for direct connections anyway.
ret = sys$qiow(0, fdtty, (IO$_SETMODE | IO$M_HANGUP),
0, 0, 0, 0, 0, 0, 0, 0, 0);
*/
sys$dassgn(fdtty);
sys$dalloc(0, 0);
sleep(2); /* To be sure DTR stays down that long */
}
/*
* Create a temporary file name for receiving a file into.
* "name" is the name we will actually eventually want to use for the file.
* We currently ignore it, but some OS's that can't move files around
* easily might want to e.g. put the temp file into the same directory
* that this file is going into.
*
* FIXME:
* This interface should be able to return a "possible" filename, and
* be re-called if the name is already in use, to get another.
* This avoids checking here whether the name is good -- saving system calls.
*/
char *
temp_filename(name)
register char *name;
{
static char tname[NAMESIZE];
if (ourpid == 0)
ourpid = getpid();
(void) sprintf(tname, "TM.u%d", ourpid);
DEBUG(7, "Using temp file %s\n", tname);
return tname;
}
/*
* Transform a filename from a uucp packet (in Unix format) into a local
* filename that will work in the local file system.
*/
char *
munge_filename(name)
register char *name;
{
int i, l, j;
int slash = 0;
char buff[NAMESIZE+SLOP];
DEBUG(7, "Munge_filename input: %s\n", name);
l = strlen(name);
for (i = l; i >= 0; i--)
if (name[i] == '/') {
slash++;
break;
}
j = 0;
for (i++; i < l; i++)
buff[j++] = name[i];
buff[j++] = '\0';
l = strlen(buff);
sprintf(name, "%s%s", slash ? Pubdir : "", buff);
DEBUG(7, "Munge_filename output: %s\n", name);
return name;
}
/*
* Uucp work queue scan.
*
* gotsome = work_scan(hostname, type);
* return 1 if files matching type.hostname* exist.
* if hostname is NULL, match type.*. Sets up template for work_next.
*
* workfile = work_next();
* Return the name of the next file to match or NULL.
*
* void work_done();
* No more matches required.
*/
int context = NULL; /* Context for lib$find_file */
char template[255]; /* Template for lib$find_file to match */
void
work_done()
{
if (context)
lib$find_file_end(&context);
context = NULL;
}
/* return 1 if type.host* exists else 0 */
int
work_scan(host, type)
char *host;
char *type;
{
int length, ret;
char *strchr();
char file_found[255];
struct dsc$descriptor_s result_dsc, file_dsc;
result_dsc.dsc$w_length = 0;
result_dsc.dsc$a_pointer = file_found;
result_dsc.dsc$b_class = DSC$K_CLASS_S;
result_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
file_dsc.dsc$w_length = strlen(template);
file_dsc.dsc$a_pointer = template;
file_dsc.dsc$b_class = DSC$K_CLASS_S;
file_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
if (!host)
host = "";
sprintf(template, "%s.%s*", type, host);
if (context)
work_done(); /* Clean up prev call, if any */
file_dsc.dsc$w_length = strlen(template);
result_dsc.dsc$w_length = sizeof(file_found);
ret = lib$find_file(&file_dsc, &result_dsc, &context);
work_done();
switch (ret) {
case RMS$_NORMAL:
return 1;
case RMS$_NMF: /* no more files */
default:
return NULL;
}
}
char *
work_next()
{
int length, ret;
char *strchr();
static char file_found[255];
struct dsc$descriptor_s result_dsc, file_dsc;
result_dsc.dsc$w_length = sizeof(file_found);
result_dsc.dsc$a_pointer = file_found;
result_dsc.dsc$b_class = DSC$K_CLASS_S;
result_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
file_dsc.dsc$w_length = strlen(template);
file_dsc.dsc$a_pointer = template;
file_dsc.dsc$b_class = DSC$K_CLASS_S;
file_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
ret = lib$find_file(&file_dsc, &result_dsc, &context);
length = strchr(file_found, ' ') - file_found;
file_found[length] = '\0';
switch (ret) {
case RMS$_NORMAL:
return file_found;
case RMS$_NMF: /* no more files */
default:
return NULL;
}
}
bcopy(from, to, cnt)
register char *from;
register char *to;
register int cnt;
{
register int i;
for (i = 0; i < cnt; i++)
*to++ = *from++;
}
bzero(s, cnt)
register char *s;
register int cnt;
{
register int i;
for (i = 0; i < cnt; i++)
*s++ = '\0';
}
rename(from, to)
char *to, *from;
{
int ifd, ofd, n;
char buff[512];
if ((ifd = open(from, 0)) < 0)
return (0);
if ((ofd = creat(to, 0)) < 0)
return (1);
while ((n = read(ifd, buff, sizeof(buff))) > 0)
write(ofd, buff, n);
if (close(ifd) < 0)
return (1);
if (close(ofd) < 0)
return (1);
delete(from);
return (0);
}
char *
strtok(string, separators)
char *string, *separators;
{
char *p;
static char *start, *last;
if (string != NULL) {
start = string;
/* skip leading separators */
while(*start && isin(*start,separators))
start++;
last = start;
}
p = start;
if (*last == NULL)
return NULL;
/* find first separator and NULL it */
while (*last && !isin(*last, separators))
last++;
*last++ = NULL;
/* find next non-separator */
while (*last && isin(*last, separators))
last++;
start = last;
return p;
}
isin(ch, setofchars)
char ch, *setofchars;
{
char *cp;
for (cp = setofchars; *cp; cp++)
if (*cp == ch)
return 1;
return 0;
}
spawn(command, input, output)
char *command, *input, *output;
{
int ret;
int status;
$DESCRIPTOR(tmp1, command);
$DESCRIPTOR(tmp2, input);
$DESCRIPTOR(tmp3, output);
tmp1.dsc$w_length = strlen(command);
tmp2.dsc$w_length = strlen(input);
tmp3.dsc$w_length = strlen(output);
ret = lib$spawn(&tmp1, &tmp2, &tmp3, 0, 0, 0, &status, 0, 0, 0);
DEBUG(1, "spawn: completed %d\n", ret);
if (!(ret & 1 && status & 1))
return (0);
return (status);
}
/*
** void pqsort(vec, nel, esize, compptr)
**
** Quick Sort routine.
** Based on Knuth's ART OF COMPUTER PROGRAMMING, VOL III, pp 114-117.
** For some unknown reason, this works faster than the library's qsort.
**
** Parameters:
** vec = points to beginning of structure to sort.
** nel = number of elements.
** esize = size of an element.
** compptr = points to the routine for comparing two elements.
**
** Returns:
** Nothing.
*/
static int elsize; /* Element size */
static int (*comp) (); /* Address of comparison routing */
static void memexch(), mysort();
void
pqsort(vec, nel, esize, compptr)
unsigned char *vec;
int nel;
int esize;
int (*compptr) ();
{
/* If less than 2 items, done */
if (nel < 2)
return;
elsize = esize;
comp = compptr;
/* Call the real worker */
mysort(vec, nel);
}
/*
** void mysort(vec, nel)
**
** The real quick sort routine.
**
** Parameters:
** vec = points to beginning of structure to sort.
** nel = number of elements.
**
** esize = size of an element.
** compptr = points to the routine for comparing two elements.
**
** Returns:
** Nothing.
*/
static void
mysort(vec, nel)
unsigned char *vec;
int nel;
{
register short i, j;
register unsigned char *iptr, *jptr, *kptr;
/* * If 2 items, check them by hand. */
begin:
if (nel == 2) {
if ((*comp) (vec, vec + elsize) > 0)
memexch(vec, vec + elsize, elsize);
return;
}
/* * Initialize for this round. */
j = nel;
i = 0;
kptr = vec;
iptr = vec;
jptr = vec + elsize * nel;
while (--j > i) {
/* * From the righthand side, find the first value that should be *
* to the left of k. */
jptr -= elsize;
if ((*comp) (jptr, kptr) > 0)
continue;
/* * Now from the lefthand side, find the first value that should be *
* to the right of k. */
iptr += elsize;
while (++i < j && (*comp) (iptr, kptr) <= 0)
iptr += elsize;
if (i >= j)
break;
/* * Exchange the two items. * k will eventually end up between them. */
memexch(jptr, iptr, elsize);
}
/* * Move item 0 into position. */
memexch(vec, iptr, elsize);
/* * Now sort the two partitions. */
if ((nel -= (i + 1)) > 1)
mysort(iptr + elsize, nel);
/* * To save a little time, just start the routine over by hand. */
if (i > 1) {
nel = i;
goto begin;
}
}
/*
** memexch(s1, s2, n)
**
** Exchange the contents of two vectors.
**
** Parameters:
** s1 = points to one vector.
** s2 = points to another vector.
** n = size of the vectors in bytes.
**
** Returns:
** Nothing.
*/
static void
memexch(s1, s2, n)
register unsigned char *s1;
register unsigned char *s2;
register int n;
{
register unsigned char c;
while (n--) {
c = *s1;
*s1++ = *s2;
*s2++ = c;
}
}
getwd(buff)
char *buff;
{
char *p = getenv("PATH");
strcpy(buff, p);
}
system(buff)
char *buff;
{
return (spawn(buff, "NL:", "NL:") & 1 == 0);
}
/*
* Routine to return a string that gives the current date and time, and
* identifies the current process, if on a multiprocess system.
*/
char *
time_and_pid()
{
long clock;
struct tm *tm;
static int ourpid = 0;
static char format[] = "%d/%d-%d:%02d:%02d-%d";
static char outbuf[sizeof(format)];
(void) time(&clock);
tm = localtime(&clock);
if (ourpid == 0)
ourpid = getpid();
sprintf(outbuf, format,
tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
ourpid);
return outbuf;
}